#include "include/Common.h"
#include "include/ConcurrentAlloc.h"
#include <thread>
#include <atomic>

// ntimes一轮申请和释放内存的次数，rounds跑多少轮，nworks线程数量
void BenchmarkMalloc(size_t ntimes, size_t nworks, size_t rounds)
{
	std::vector<std::thread> vthread(nworks);
	std::atomic<size_t> malloc_costtime;
	malloc_costtime = 0;
	std::atomic<size_t> free_costtime;
	free_costtime = 0;
	for (size_t k = 0; k < nworks; ++k)
	{
		vthread[k] = std::thread([&, k]()
								 {
			std::vector<void*> v;
			v.reserve(ntimes);
			for (size_t j = 0; j < rounds; ++j)
			{
				size_t begin1 = clock();
				for (size_t i = 0; i < ntimes; i++)
				{
					//v.push_back(malloc(16));
					v.push_back(malloc((16 + i) % 8192 + 1));
				}
				size_t end1 = clock();
				size_t begin2 = clock();
				for (size_t i = 0; i < ntimes; i++)
				{
					free(v[i]);
				}
				size_t end2 = clock();
				v.clear();
				malloc_costtime += (end1 - begin1);
				free_costtime += (end2 - begin2);
			} });
	}
	for (auto &t : vthread)
	{
		t.join();
	}
	printf("%lu个线程并发执行%lu轮次，每轮次concurrent alloc %lu次: 花费：%.2lf ms\n",
		   nworks, rounds, ntimes, (double)malloc_costtime / CLOCKS_PER_SEC * 1000);
	printf("%lu个线程并发执行%lu轮次，每轮次concurrent dealloc %lu次: 花费：%.2lf ms\n",
		   nworks, rounds, ntimes, (double)free_costtime / CLOCKS_PER_SEC * 1000);
	printf("%lu个线程并发concurrent alloc&dealloc %lu次，总计花费：%.2lf ms\n",
		   nworks, nworks * rounds * ntimes, ((double)malloc_costtime + (double)free_costtime) / CLOCKS_PER_SEC * 1000);
}

void BenchmarkConcurrentMalloc(size_t ntimes, size_t nworks, size_t rounds)
{
	std::vector<std::thread> vthread(nworks);
	std::atomic<size_t> malloc_costtime;
	malloc_costtime = 0;
	std::atomic<size_t> free_costtime;
	free_costtime = 0;
	for (size_t k = 0; k < nworks; ++k)
	{
		vthread[k] = std::thread([&]()
								 {
			std::vector<void*> v;
			v.reserve(ntimes);
			for (size_t j = 0; j < rounds; ++j)
			{
				size_t begin1 = clock();
				for (size_t i = 0; i < ntimes; i++)
				{
					//v.push_back(ConcurrentAlloc(16));
					v.push_back(ConcurrentAlloc((16 + i) % 8192 + 1));
				}
				size_t end1 = clock();
				size_t begin2 = clock();
				for (size_t i = 0; i < ntimes; i++)
				{
					ConcurrentFree(v[i]);
				}
				Clear();
				size_t end2 = clock();
				v.clear();
				malloc_costtime += (end1 - begin1);
				free_costtime += (end2 - begin2);
			}
			//线程结束前调用Clear()清理ThreadCache
			Clear(); });
	}
	for (auto &t : vthread)
	{
		t.join();
	}
	printf("%lu个线程并发执行%lu轮次，每轮次concurrent alloc %lu次: 花费：%.2lf ms\n",
		   nworks, rounds, ntimes, (double)malloc_costtime / CLOCKS_PER_SEC * 1000);
	printf("%lu个线程并发执行%lu轮次，每轮次concurrent dealloc %lu次: 花费：%.2lf ms\n",
		   nworks, rounds, ntimes, (double)free_costtime / CLOCKS_PER_SEC * 1000);
	printf("%lu个线程并发concurrent alloc&dealloc %lu次，总计花费：%.2lf ms\n",
		   nworks, nworks * rounds * ntimes, ((double)malloc_costtime + (double)free_costtime) / CLOCKS_PER_SEC * 1000);
}

void test()
{
	std::vector<void *> v;
	v.reserve(10000);
	for (size_t j = 0; j < 4; ++j)
	{
		size_t begin1 = clock();
		for (size_t i = 0; i < 10000; i++)
		{
			// v.push_back(ConcurrentAlloc(16));
			v.push_back(ConcurrentAlloc((16 + i) % 8192 + 1));
		}
		size_t end1 = clock();
		size_t begin2 = clock();
		for (size_t i = 0; i < 10000; i++)
		{
			ConcurrentFree(v[i]);
		}
		v.clear();
	}
	Clear();
}
int main()
{
	size_t n = 10000;
	cout << "==========================================================" << endl;
	BenchmarkConcurrentMalloc(n, 4, 10);
	cout << endl
		 << endl;
	BenchmarkMalloc(n, 4, 10);
	cout << "==========================================================" << endl;

	// test();
	return 0;
}